home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Utilities / ODNewObj.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  9.1 KB  |  386 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODNewObj.cpp
  3.  
  4.     Contains:    Abstract wrapper for instantiating objects by class-name
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1994 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <8>     8/13/96    DM        1377223: instantiating parts in shell
  13.                                     plugins
  14.          <7>      7/2/96    TJ        Only load fragments of the current arc.
  15.          <6>     6/27/96    TJ        T10003 Load editors of type oded also.
  16.          <5>     6/27/96    jpa        1361886: Return error string
  17.          <4>     6/21/96    jpa        T10002: Don't check app heap space if
  18.                                     NewPtr override exists.
  19.          <3>     1/23/96    VL        1170098: Put back the CFM loading code
  20.                                     removed in the last checkin. The code was
  21.                                     used for debugging and getting CFM errors.
  22.          <2>     1/16/96    VL        1170098: Removed code for GetSharedLibrary.
  23.  
  24.     To Do:
  25. */
  26.  
  27.  
  28. #ifndef _ODMEMORY_
  29. #include "ODMemory.h"
  30. #endif
  31.  
  32. #ifndef _BARRAY_
  33. #include <BArray.h>
  34. #endif
  35.  
  36. #ifndef SOM_ODBinding_xh
  37. #include <ODBindng.xh>
  38. #endif
  39.  
  40. #ifndef _BNDNSUTL_
  41. #include "BndNSUtl.h"
  42. #endif
  43.  
  44. #ifndef _ODNEWOBJ_
  45. #include "ODNewObj.h"
  46. #endif
  47.  
  48. #ifndef _PLFMDEF_
  49. #include "PlfmDef.h"
  50. #endif
  51.  
  52. #ifndef _MEMMGR_
  53. #include <MemMgr.h>
  54. #endif
  55.  
  56. #ifndef _EXCEPT_
  57. #include "Except.h"
  58. #endif
  59.  
  60. #ifndef _ODDEBUG_
  61. #include "ODDebug.h"
  62. #endif
  63.  
  64. #ifndef _ODUTILS_
  65. #include <ODUtils.h>
  66. #endif
  67.  
  68. #ifndef _PASCLSTR_
  69. #include <PasclStr.h>
  70. #endif
  71.  
  72. #ifndef _UTILERRS_
  73. #include "UtilErrs.h"
  74. #endif
  75.  
  76. #ifndef __SOM__
  77. #include <som.xh>
  78. #endif
  79.  
  80. #ifndef SOM_SOMClassMgr_xh
  81. #include <somcm.xh>
  82. #endif
  83.  
  84. #ifndef _ISOSTR_
  85. #include "ISOStr.h"
  86. #endif
  87.  
  88. #ifdef _PLATFORM_MACINTOSH_
  89.  
  90.     #ifndef __STRINGS__
  91.     #include <strings.h>
  92.     #endif
  93.     
  94.     #include <CodeFragments.h>
  95.     
  96.     #ifndef __FILES__
  97.     #include <Files.h>
  98.     #endif
  99.  
  100.     #define LOAD_UNDER_ASSUMED_NAME   1
  101.     /*    SOM requires that the library name (in the 'cfrg') be of the form "Module::ClassName".
  102.         This obviously won't match the library's SYM file name. This causes problems for source
  103.         level debuggers; they can't associate the two and you end up not being able to debug
  104.         the library.
  105.         To work around this, we give the library two names (two 'cfrg' entries), the second of
  106.         which is just the classname. Then if the SYM file name matches the classname, we can first
  107.         load the library by the classname, which will signal the debugger that it can link the
  108.         library up with the similarly-named SYM file.
  109.         Got that?? Off we go!!
  110.     */
  111. #endif
  112.  
  113. #ifndef _ODDEBUG_
  114. #include "ODDebug.h"
  115. #endif
  116.  
  117.  
  118. const ODSize kMinAppFreeSpace =        48 * 1024;    // Only if we can't override NewPtr
  119. const ODSize kMinAppContigSpace =     8 * 1024;
  120.  
  121. const unsigned char kMemoryLibName[]        = "\pMemory Manager",
  122.                     kMemoryOverrideOnName[] = "\pMMOverridePlatform",
  123.                     kMemoryOverrideOffName[]= "\pMMEndOverridePlatform";
  124.  
  125. extern "C" {
  126.     typedef void (*MemoryOverrideProcPtr)( MMBoolean ptrs, MMBoolean handles );
  127. }
  128.  
  129. static somTD_SOMError            *gOld_SOMError;
  130.  
  131.  
  132. static ODBoolean    TryToOverrideNewPtr( ODBoolean onoff );
  133.  
  134.  
  135. extern "C" {
  136.     static void
  137.     Temp_GetClass_SOMError( int error, corbastring filename, int linenum );
  138. }
  139.  
  140.  
  141. static void
  142. Temp_GetClass_SOMError( int error, corbastring filename, int linenum )
  143. {
  144.     int severity = error % 10;
  145.     if( severity == SOM_Fatal ) {
  146.         WARN("Fatal SOM err %d caught during GetClass; throwing...",error);
  147.         THROW(error);
  148.     } else if( gOld_SOMError )
  149.         gOld_SOMError(error,filename,linenum);
  150. }
  151.  
  152.  
  153. static SOMClass*
  154. GetClass( const char *className, Str255 errorString = kODNULL )
  155. {
  156.     char libname[64];
  157. #if PRAGMA_ALIGN_SUPPORTED
  158. #pragma options align=mac68k
  159. #endif
  160.  
  161.     struct FragDesc {
  162.         ResType codeType;
  163.         long ignore[5];
  164.         long offsetToFrag;
  165.         long lengthOfFrag;
  166.         long moreIgnore[2];
  167.         short recordLength;
  168.         Str63 name;
  169.     };
  170.     
  171.     struct CFRGResource {
  172.         long ignore[7];
  173.         long numFrags;
  174.         struct FragDesc firstDesc;
  175.     };
  176.  
  177. #if PRAGMA_ALIGN_SUPPORTED
  178. #pragma options align=reset
  179. #endif
  180.  
  181. #if LOAD_UNDER_ASSUMED_NAME
  182.     // First grab everything after the last colon in className:
  183.     const char *lastcolon = strrchr(className,':');
  184.     if (lastcolon == nil) {
  185.         // Hack to load Bento:
  186.         if( strcmp(className,"ODFileContainer")==0 ||
  187.             strcmp(className,"ODMemContainer")==0 ||
  188.             strcmp(className,"ODEmbeddedContainer")==0 )
  189.                 strcpy(libname, "OpenDoc Bento");
  190.         else
  191.                 strcpy(libname, className);
  192.     }
  193.     else {
  194.         strncpy(libname,lastcolon+1,sizeof(libname)-1);
  195.         libname[sizeof(libname)-1] = '\0';
  196.     }
  197. #else
  198.     strcpy(libname,className);
  199. #endif /*LOAD_UNDER_ASSUMED_NAME*/
  200.  
  201.     if( errorString ) errorString[0] = '\0';
  202.     
  203.     c2pstr(libname);
  204.  
  205.     CFragConnectionID connID;
  206.     Ptr mainAddr;
  207.     Str255 errName;
  208.     ODBoolean unloadLib = kODFalse;
  209.     
  210.     // Either override NewPtr or at least make sure there's memory available:
  211.     ODBoolean override = TryToOverrideNewPtr(kODTrue);
  212.     if( !override )
  213.         ODRequireFreeSpace(kMinAppFreeSpace,kMinAppContigSpace,kODTrue);
  214.     
  215.     // First see if the library is already loaded:
  216.     OSErr err = GetSharedLibrary((StringPtr)libname, kCurrentCFragArch,
  217.                                 kFindCFrag, &connID,&mainAddr,errName);
  218.                                 
  219.     if( err == fragLibNotFound || err==fragLibConnErr ) 
  220.     {
  221.         // Nope, need to load it:
  222.         ODByteArray ba = CreateEmptyByteArrayStruct(sizeof(ODFileSpec));
  223.         ODVolatile(ba);
  224.         TRY
  225.         Environment* ev = somGetGlobalEnvironment();
  226.         ODFileSpec* fsspecPtr = kODNULL;
  227.         if (GetgBinding()->GetODFileSpecFromEditor(ev,ODISOStrFromCStr(className),&ba))
  228.         {
  229.             fsspecPtr = (ODFileSpec*)((&ba)->_buffer);
  230.             short refNum = HOpenResFile( fsspecPtr->vRefNum, fsspecPtr->parID,
  231.             fsspecPtr->name, fsRdPerm );
  232.             short saveRefNum = CurResFile();
  233.             WASSERT(ResError()==noErr);
  234.             if (refNum != -1)
  235.             {
  236.                 UseResFile( refNum );            
  237.                 struct CFRGResource** cfrgHandle =
  238.                     (struct CFRGResource**)Get1Resource( 'cfrg', 0 );
  239.                 if ( cfrgHandle )
  240.                 {
  241.                     long entryCount = (*cfrgHandle)->numFrags;
  242.                     struct FragDesc* oneEntryPtr = &(*cfrgHandle)->firstDesc;
  243.                     while ( entryCount-- )
  244.                     {
  245.                     if ( oneEntryPtr->codeType == kCurrentCFragArch &&
  246.                         EqualPascalStrings((StringPtr)libname,oneEntryPtr->name))
  247.                         {
  248.                             err = GetDiskFragment(fsspecPtr, oneEntryPtr->offsetToFrag,
  249.                             oneEntryPtr->lengthOfFrag,NULL,
  250.                                   kLoadCFrag, &connID,&mainAddr,errName);
  251.                             break;
  252.                         }
  253.                         else
  254.                             oneEntryPtr = (FragDesc*)(oneEntryPtr->recordLength
  255.                                 + (char*)oneEntryPtr);
  256.  
  257.                     }
  258.                 }
  259.             }
  260.             CloseResFile( refNum );
  261.             UseResFile( saveRefNum );
  262.         }
  263.         else
  264.             err = GetSharedLibrary((StringPtr)libname, kCurrentCFragArch,
  265.                                 kLoadCFrag, &connID, &mainAddr, errName);
  266.     
  267.         DisposeByteArrayStruct(ba);
  268.         CATCH_ALL
  269.             DisposeByteArrayStruct(ba);
  270.             RERAISE;
  271.         ENDTRY
  272.         if( err==noErr && !override && !ODHaveFreeSpace(kMinAppFreeSpace,
  273.                                                         kMinAppContigSpace,kODTrue) ) {
  274.             CloseConnection(&connID);
  275.             err = fragNoMem;
  276.     #if ODDebug
  277.             CopyPascalString(errName,"\pOD free space too low");
  278.     #endif
  279.         }
  280.         else
  281.             unloadLib = kODTrue;
  282.     }
  283.     
  284.     if( override )
  285.         TryToOverrideNewPtr(kODFalse);            // turn off override
  286.  
  287.     if( err ) {
  288.         if( errorString )
  289.             CopyPascalString(errorString,errName);
  290.         p2cstr(errName);
  291.         WARN("Can't load lib '%s'; error %hd, '%s'",
  292.                 p2cstr((StringPtr)libname),err,errName);
  293.         THROW(err,(char*)errName);
  294.     }
  295.     
  296.     /* Now try to load the class. Install a temporary error handler that
  297.         converts a fatal SOM error into a THROW, in case SOM runs out of
  298.         memory. */
  299.     SOMClass *c;
  300.     gOld_SOMError = SOMError;
  301.     SOMError = &Temp_GetClass_SOMError;
  302.     TRY{
  303.         long majorVersion = 0;
  304.         long minorVersion = 0;
  305.         somId id = somIdFromString((corbastring)className);
  306.         c = somGetDynamicClassReference(id,majorVersion,minorVersion, kODNULL);
  307.         SOMFree(id);
  308.         if (unloadLib)
  309.         {
  310.             unloadLib = kODFalse;
  311.             CloseConnection(&connID);
  312.         }
  313.     }CATCH_ALL{
  314.         if (unloadLib)
  315.             CloseConnection(&connID);
  316.         SOMError = gOld_SOMError;
  317.         RERAISE;
  318.     }ENDTRY
  319.     SOMError = gOld_SOMError;
  320.         
  321.     
  322.     if( !c )
  323.         THROW(kODErrCantLoadSOMClass);
  324.     return c;
  325. }
  326.  
  327.  
  328. SOMObject*
  329. ODNewObject( const char *className, Str255 errorString )
  330. {
  331.     SOMClass *cls = GetClass(className,errorString);
  332.     THROW_IF_NULL (cls);  // would have thrown anyway...
  333.     SOMObject* obj = cls->somNew();
  334.     somReleaseClassReference(cls); // must release class reference
  335.     THROW_IF_NULL (obj); // similar to new ODObject, must throw if nil
  336.     return obj;
  337. }
  338.  
  339.  
  340. ODBoolean
  341. ODClassExists( const char *className )
  342. {
  343.     /* This function will now propagate errors if the library _does_ exist
  344.        but just couldn't be loaded due to e.g. insufficient memory or missing
  345.        imports. This allows for better error display to the user since otherwise
  346.        the error would be eaten and replaced with a simple Boolean return value. */
  347.     
  348.     ODBoolean result = kODTrue;
  349.     TRY
  350.         SOMClass *cls = GetClass(className);
  351.         somReleaseClassReference ( cls );
  352.     CATCH_ALL
  353.         if( ErrorCode()==kODErrCantLoadSOMClass || ErrorCode()==fragLibNotFound )
  354.             result = kODFalse;
  355.         else
  356.             RERAISE;
  357.     ENDTRY
  358.     return result;
  359. }
  360.  
  361.  
  362. static ODBoolean
  363. TryToOverrideNewPtr( ODBoolean onoff )
  364. {
  365.     Str255 errName;
  366.     CFragConnectionID connID;
  367.     Ptr mainAddr;
  368.     OSErr err = GetSharedLibrary(kMemoryLibName, kCurrentCFragArch,
  369.                                 kLoadCFrag, &connID,&mainAddr,errName);
  370.     if( err ) {
  371.         WARN("Couldn't find Memory Mgr?? %d, %s", err,p2cstr(errName));
  372.         return kODFalse;
  373.     }
  374.     
  375.     MemoryOverrideProcPtr proc;
  376.     CFragSymbolClass type;
  377.     err= FindSymbol(connID, onoff ?kMemoryOverrideOnName :kMemoryOverrideOffName, (Ptr*)&proc, &type);
  378.     if( err ) {
  379.         WASSERT(err==fragSymbolNotFound);
  380.         return kODFalse;
  381.     }
  382.     
  383.     (*proc)(true,false);        // Call proc
  384.     return kODTrue;
  385. }
  386.